package fast.mvc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import indzcraft.loader.BaseStats;
import indzcraft.loader.Database;
import indzcraft.loader.Enchant;
import indzcraft.loader.EnchantDB;
import indzcraft.loader.Equipment;
import indzcraft.loader.Gem;
import indzcraft.loader.GemDB;
import indzcraft.loader.IndzCraftLoader;
import indzcraft.loader.Item;
import indzcraft.loader.ItemEquipped;
import indzcraft.loader.RaceDB;
import indzcraft.loader.Reforge;
import indzcraft.loader.ReforgeDB;
import indzcraft.loader.Slot;
import indzcraft.loader.SocketBonus;
import indzcraft.loader.Weapon;

import org.json.JSONException;

import fast.calc.Fast;
import fast.calc.Stats;

public class Model {

    Fast fast;
    private Database db;
    private IndzCraftLoader loader;
    private Equipment equipment;
    private Settings settings = new Settings();

    public Model(){
        reset();
    }

    public void reset(){
        fast = null;
        loader = new IndzCraftLoader();
        db = new Database(loader);
		loader.setDatabase(db);
		setEquipment(loader.getEquipment());
		fillEquipment();
    }
    
    public void calcFast(){
    	if(equipment.equipment.isEmpty() || equipment.get(Slot.mainHand) == null || equipment.get(Slot.offHand) == null)
    		return;
    	/*if(		loader.getBase().getSpec() == Spec.Assassination 
    			&& (!equipment.get(Slot.mainHand).getItem().getWeaponTypeName().equals(WeaponType.dagger.name())
    			|| !equipment.get(Slot.offHand).getItem().getWeaponTypeName().equals(WeaponType.dagger.name()))){
    		System.out.println("test");
    		return;
    	}*/
    	BaseStats base = new BaseStats();
    	
		base.setRace(loader.getBase().getRace());
		base.setSpec(loader.getBase().getSpec());
		base.setGlyphs(loader.getBase().getGlyphs());
		
		ItemEquipped mhe = equipment.get(Slot.mainHand);
		String enchant = "";
		if(mhe.getEnchant() != null)
			enchant = mhe.getEnchant().getName();
		Weapon mh = new Weapon(mhe.getItem().getSpeed(),mhe.getItem().getDps(),mhe.getItem().getWeaponTypeName(),enchant);
		base.setMH(mh);
		
		ItemEquipped ohe = equipment.get(Slot.offHand);
		enchant = "";
		if(ohe.getEnchant() != null)
			enchant = ohe.getEnchant().getName();
		Weapon oh = new Weapon(ohe.getItem().getSpeed(),ohe.getItem().getDps(),ohe.getItem().getWeaponTypeName(),enchant);
		base.setOH(oh);
		
		ItemEquipped item = null;
		for(Slot name: equipment.equipment.keySet()){
			item = equipment.get(name);
			if(item == null)
				continue;
			base.incStr(item.getItem().getStr());
			base.incAgi(item.getItem().getAgi());
			base.incHaste(item.getReforgedHaste());
			base.incMastery(item.getReforgedMastery());
			base.incExp(item.getReforgedExp());
			base.incCrit(item.getReforgedCrit());
			base.incHit(item.getReforgedHit());
			
			boolean colorMatch = true;
			for(int j = 0; j < 3;j++){
				if(	(name == Slot.wrist || name == Slot.hands)
					&& item.getItem().gemSlot[j].equals("PRISMATIC")
					&& !loader.getBase().getProfessions().contains("Blacksmithing") ){
					System.out.println("no blacksmith, so blacksmith sockets will be skipped.");
					continue;
				}
				if(item.getGem(j) != null){
					base.incAgi(item.getGem(j).getAgi());
					base.incHaste(item.getGem(j).getHaste());
					base.incHit(item.getGem(j).getHit());
					base.incMastery(item.getGem(j).getMastery());
					
					int type = item.getGem(j).getType();
					if(item.getItem().gemSlot[j].equals("RED") && (type != Gem.RED && type != Gem.ORANGE && type != Gem.PURPLE)){
						colorMatch = false;
					}
					else if(item.getItem().gemSlot[j].equals("YELLOW") && (type != Gem.YELLOW && type != Gem.ORANGE && type != Gem.GREEN)){
						colorMatch = false;
					}
					else if(item.getItem().gemSlot[j].equals("BLUE") && (type != Gem.BLUE && type != Gem.PURPLE && type != Gem.GREEN)){
						colorMatch = false;
					}
					else if(item.getItem().gemSlot[j].equals("META") && type != Gem.META){
						colorMatch = false;
					}
					if(item.getGem(j).getGearBuff() != null){
						base.addGearBuff(item.getGem(j).getGearBuff());
					}
				}
			}
			if(item.getItem().socketBonus != null && colorMatch){
				base.incAgi(item.getItem().socketBonus.getAgi());
				base.incHaste(item.getItem().socketBonus.getHaste());
				base.incMastery(item.getItem().socketBonus.getMastery());
				base.incExp(item.getItem().socketBonus.getExp());
				base.incCrit(item.getItem().socketBonus.getCrit());
				base.incHit(item.getItem().socketBonus.getHit());
			}
			Enchant en = item.getEnchant();
			if(	(name == Slot.finger1 || name == Slot.finger2) 
				&& !loader.getBase().getProfessions().contains("Enchanting")){
				System.out.println("no enchanter, so ring enchants will be skipped.");
			}
			else if(en != null){
				base.incStr(en.getStr());
				base.incAgi(en.getAgi());
				base.incHaste(en.getHaste());
				base.incMastery(en.getMastery());
				base.incExp(en.getExp());
				base.incCrit(en.getCrit());
				base.incHit(en.getHit());
				base.incAp(en.getAp());
			}
			// set item
			if(item.getItem().getSet() != null && !item.getItem().getSet().equals("")){
				//System.out.println("tt " + item.getSet());
				base.addSetItem(item.getItem().getSet());
			}else if(item.getItem().getSet() == null){
				System.out.println("Error: Setitem found which is not in ItemSetDB. ItemID: "+ item.getItem().getId());
			}
			if(item.getItem().getGearBuff() != null){
				base.addGearBuff(item.getItem().getGearBuff());
			}
		}
		// Race
		String race = base.getRace();
		RaceDB rdb = new RaceDB();
		indzcraft.loader.Race r = rdb.findByName(race);
		if(r != null){
			base.incAgi(r.getAgi());
			base.incStr(r.getStr());
		}
		
		if(loader.getBase().getProfessions().contains("Engineering")){
			base.addGearBuff("synapse_springs");
		}
		if(equipment.get(Slot.back) != null && loader.getEnchantDB().getEnchant(4894) != null && equipment.get(Slot.back).getEnchant() == loader.getEnchantDB().getEnchant(4894)){
			base.addGearBuff("swordguard_embroidery");
		}
		if(loader.getBase().getProfessions().contains("Skinning")){
			base.incCrit(480);
		}
		if(loader.getBase().getProfessions().contains("Herbalism")){
			base.addGearBuff("lifeblood");
		}
		if(loader.getBase().getRace().equals("troll")){
			base.addGearBuff("berserking");
		}
		if(loader.getBase().getRace().equals("orc")){
			base.addGearBuff("blood_fury");
		}
		if(loader.getBase().getRace().equals("bloodelf")){
			base.addGearBuff("arcane_torrent");
		}
		if(loader.getBase().getRace().equals("goblin")){
			base.addGearBuff("time_is_money");
		}
		if(loader.getBase().getRace().equals("pandaren")){
			base.addGearBuff("epicurean");
		}
		if(loader.getBase().getRace().equals("worgen")){
			base.addGearBuff("viciousness");
		}
		if(settings.isCombatUseRupture())
			base.addGearBuff("combat_use_rupture");
		if(settings.isUseAndGetTott())
			base.addGearBuff("use_and_get_tott");
    	
    	fast = new Fast(base);
    }
    
    public double getDPS(){
    	if(fast == null)
    		return 0.0;
    	return fast.getDps();
    }

	public void loadCharacter(String region, String server, String player){
		try {
			System.out.println(player + " from " + server + "-"+ region);
			loader = new IndzCraftLoader();
			db = new Database(loader);
			loader.setDatabase(db);
			loader.load2(player, server, region, true);
			setEquipment(loader.getEquipment());
		} 
		catch (JSONException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}
	
	public double calcItemEP(Item item,Slot slot){
		if(fast == null)
			return item.getItemLevel();
		double ep = 0.;
		Map<String, Double> statsEP = fast.getEP();
		ep += statsEP.get("agi")*item.getAgi();
		ep += statsEP.get("white_hit")*item.getHit();
		ep += statsEP.get("exp")*item.getExp();
		ep += statsEP.get("haste")*item.getHaste();
		ep += statsEP.get("mastery")*item.getMastery();
		ep += statsEP.get("crit")*item.getCrit();
		
		
		if(Slot.mainHand == slot){
			ep += statsEP.get("mh_dps")*item.getDps();
			if(item.getSpeed() >= 1.4)
				ep += statsEP.get("mh_speed_"+item.getSpeed());
			ep += statsEP.get("mh_type_"+item.getWeaponTypeName());
		}else if(Slot.offHand == slot){
			ep += statsEP.get("oh_dps")*item.getDps();
			if(item.getSpeed() >= 1.4){
				ep += statsEP.get("oh_speed_"+item.getSpeed());
			}
		}
		
		// gems
		Gem bestRed = getBestGem("RED");
		Gem bestYellow = getBestGem("YELLOW");
		Gem bestBlue = getBestGem("BLUE");
		Gem bestHydraulic = getBestGem("HYDRAULIC");
		
		double bestRedEP = calcGemEP(bestRed);
		double bestYellowEP = calcGemEP(bestYellow);
		double bestBlueEP = calcGemEP(bestBlue);
		double bestHydraulicEP = calcGemEP(bestHydraulic);
		
		//Gem bestGem = bestRed;
		double bestGemEP = bestRedEP;
		if(bestYellowEP > bestGemEP){
			//bestGem = bestYellow; 
			bestGemEP = bestYellowEP;
		}
		if(bestBlueEP > bestRedEP){
			//bestGem = bestBlue; 
			bestGemEP = bestBlueEP;
		}
		double gemMatchEP = 0.;
		String[] gemSlot = item.getGemSlot();
		for(int i = 0;i< gemSlot.length;i++){
			if(gemSlot[i].equals("RED") || gemSlot[i].equals("PRISMATIC")){
				gemMatchEP += bestRedEP;
			}else if(gemSlot[i].equals("YELLOW")){
				gemMatchEP += bestYellowEP;
			}else if(gemSlot[i].equals("BLUE")){
				gemMatchEP += bestBlueEP;
			}else if(gemSlot[i].equals("HYDRAULIC")){
				gemMatchEP += bestHydraulicEP;
			}
		}
		
		//System.out.println("gem Match EP: " + gemMatchEP);
		
		double gemOnlyBestEP = 0.;
		//boolean gemOnlyBestMatch = true;
		for(int i = 0;i< gemSlot.length;i++){
			if(!gemSlot[i].equals("")){
				gemOnlyBestEP += bestGemEP;
			}
		}
		
		//System.out.println(gemOnlyBestEP);
		
		double gemSocketEP = 0.;
		if(item.getSocketBonus() != null){
			SocketBonus sb = item.getSocketBonus();
			gemSocketEP += statsEP.get("agi")*sb.getAgi();
			gemSocketEP += statsEP.get("white_hit")*sb.getHit();
			gemSocketEP += statsEP.get("exp")*sb.getExp();
			gemSocketEP += statsEP.get("haste")*sb.getHaste();
			gemSocketEP += statsEP.get("mastery")*sb.getMastery();
			gemSocketEP += statsEP.get("crit")*sb.getCrit();
		}
		//System.out.println("gem socket ep:" + item.getName() + " " + gemSocketEP);
		gemMatchEP += gemSocketEP;
		
		//if(gemOnlyBestMatch)
		//	gemOnlyBestEP += gemSocketEP;
		//System.out.println("gemMatchEP" + item.getName() + " " + gemMatchEP);
		//System.out.println("gemOnlyBestEP" + item.getName() + " " + gemOnlyBestEP);
		ep += Math.max(gemMatchEP, gemOnlyBestEP);
		
		
		// TODO get Best Reforge option (e.g. crit->exp) DONE????
		Entry<String, Double> min = null;
		Entry<String, Double> max = null;
		for (Entry<String, Double> entry : statsEP.entrySet()) {
		    if(Arrays.asList(new String[]{"exp","white_hit","crit","haste","mastery"}).contains(entry.getKey())) {
		    	if(hasItemStat(item,entry.getKey()) && (min == null || min.getValue() > entry.getValue())) {
			        min = entry;
			    }
			    if(!hasItemStat(item,entry.getKey()) && (max == null || max.getValue() < entry.getValue())) {
			    	max = entry;
			    }
		    }
		}
//		System.out.println(min.getKey() + " " + min.getValue());
//		System.out.println(max.getKey() + " " + max.getValue());
		if(min != null && max != null){
			int value = 0;
			if(min.getKey().equals("crit")){
				value = (int)Math.floor(item.getCrit()*0.4);
			}else if(min.getKey().equals("haste")){
				value = (int)Math.floor(item.getHaste()*0.4);
			}else if(min.getKey().equals("white_hit")){
				value = (int)Math.floor(item.getHit()*0.4);
			}else if(min.getKey().equals("mastery")){
				value = (int)Math.floor(item.getMastery()*0.4);
			}else if(min.getKey().equals("exp")){
				value = (int)Math.floor(item.getExp()*0.4);
			}
			double lowEP = min.getValue()*value;
			double highEP = max.getValue()*value;
			
			//System.out.println(item.getName() + " " + value + " " + lowEP + " " + highEP);
			
			ep += highEP - lowEP;
		}
		
		// gearbuffs...
		if(item.getGearBuff() != null){
			try{
				ep += statsEP.get(item.getGearBuff());
			}catch(Exception e){
				System.out.println("missing: " + item.getName() + " " + item.getGearBuff());
				View.showError("missing: " + item.getName() + " " + item.getGearBuff());
			}
		}
		return ep;
	}
	
	public boolean hasItemStat(Item item, String matchingEP){
		if(matchingEP.equals("white_hit") && item.getHit() > 0){
			return true;
		}else if(matchingEP.equals("crit") && item.getCrit() > 0){
			return true;
		}else if(matchingEP.equals("haste") && item.getHaste() > 0){
			return true;
		}else if(matchingEP.equals("mastery") && item.getMastery() > 0){
			return true;
		}else if(matchingEP.equals("exp") && item.getExp() > 0){
			return true;
		}
		return false;
	}
	
	public Reforge getBestReforge(Item item){
		ReforgeDB reforgeDB = loader.getReforgeDB();
		ArrayList<Reforge> items = new ArrayList<Reforge>();
		for ( Reforge elem : reforgeDB.getDB().values() ){
			if(hasItemStat(item,"white_hit") && elem.getFrom().equals("Hit Rating"))
				items.add(elem);
			else if(hasItemStat(item,"crit") && elem.getFrom().equals("Crit Rating"))
				items.add(elem);
			else if(hasItemStat(item,"haste") && elem.getFrom().equals("Haste Rating"))
				items.add(elem);
			else if(hasItemStat(item,"mastery") && elem.getFrom().equals("Mastery Rating"))
				items.add(elem);
			else if(hasItemStat(item,"exp") && elem.getFrom().equals("Expertise Rating"))
				items.add(elem);
			if(hasItemStat(item,"white_hit") && elem.getTo().equals("Hit Rating"))
				items.remove(elem);
			else if(hasItemStat(item,"crit") && elem.getTo().equals("Crit Rating"))
				items.remove(elem);
			else if(hasItemStat(item,"haste") && elem.getTo().equals("Haste Rating"))
				items.remove(elem);
			else if(hasItemStat(item,"mastery") && elem.getTo().equals("Mastery Rating"))
				items.remove(elem);
			else if(hasItemStat(item,"exp") && elem.getTo().equals("Expertise Rating"))
				items.remove(elem);
		}
		double best = 0;
		Reforge bestReforge = null;
		for ( Reforge elem : items ){
			double reforgeEP = calcReforgeEP(item, elem);
			if(bestReforge == null || reforgeEP > best){
				bestReforge = elem;
				best = reforgeEP;
			}
		}
		return bestReforge;
	}
	
	public Enchant getBestEnchant(Slot s){
		String slotName = s.getName();
        if(slotName.endsWith("1") || slotName.endsWith("2")){
        	slotName = slotName.substring(0, slotName.length()-1);
        }else if(slotName.equals("mainHand") || slotName.equals("offHand")){
        	slotName = "weapon";
        }
		
		EnchantDB enchantDB = loader.getEnchantDB();
		
		boolean isPlayerEnchanter = loader.getBase().getProfessions().contains("Enchanting");
		boolean isPlayerLeatherworker = loader.getBase().getProfessions().contains("Leatherworking");
		boolean isPlayerInscripter = loader.getBase().getProfessions().contains("Inscription");
		boolean isPlayerTailor = loader.getBase().getProfessions().contains("Tailoring");
		double best = 0;
		Enchant bestEnchant = null;
		for ( Enchant elem : enchantDB.getDB().values() ){
			// enchanter only enchants
			if(elem.isEnchanterOnly() && !isPlayerEnchanter){
				continue;
			}
			if(elem.isLeatherworkerOnly() && !isPlayerLeatherworker){
				continue;
			}
			if(elem.isInscripterOnly() && !isPlayerInscripter){
				continue;
			}
			if(elem.isTailorOnly() && !isPlayerTailor){
				continue;
			}
			if(elem.getExp() > 0 && settings.isIgnoreExp()){
				continue;
			}
			if(elem.getSlotName().equals(slotName)){
				double enchantEP = calcEnchantEP(elem, s);
				if(bestEnchant == null || enchantEP > best){
					bestEnchant = elem;
					best = enchantEP;
				}
					
			}	

		}
		return bestEnchant;
	}
	
	public Gem getBestGem(String gemSlotColor){
		GemDB gemDB = loader.getGemDB();
		boolean isPlayerJC = loader.getBase().getProfessions().contains("Jewelcrafting");
		boolean isPlayerEng = loader.getBase().getProfessions().contains("Engineering");
		double best = 0;
		Gem bestGem = null;
		for ( Gem elem : gemDB.getDB().values() ){
			// 755 jewelcrafting
			if(elem.getReqSkill() == 755 && !isPlayerJC){
				continue;
			}
			else if(elem.getReqSkill() == 202 && !isPlayerEng){
				continue;
			}
			if(elem.getExp() > 0 && settings.isIgnoreExp()){
				continue;
			}
			boolean valid_gem = false;
			if(gemSlotColor.equals("META")){
				if(elem.getType() == Gem.META)
					valid_gem = true;
			}
			else if(gemSlotColor.equals("RED")){
				if(elem.getType() == Gem.RED || elem.getType() == Gem.ORANGE || elem.getType() == Gem.PURPLE)
					valid_gem = true;
			}
			else if(gemSlotColor.equals("YELLOW")){
				if(elem.getType() == Gem.YELLOW || elem.getType() == Gem.ORANGE || elem.getType() == Gem.GREEN)
					valid_gem = true;
			}
			else if(gemSlotColor.equals("BLUE")){
				if(elem.getType() == Gem.BLUE || elem.getType() == Gem.GREEN || elem.getType() == Gem.PURPLE)
					valid_gem = true;
			}
			else if(gemSlotColor.equals("PRISMATIC")){
				if(elem.getType() != Gem.COGWHEEL && elem.getType() != Gem.HYDRAULIC && elem.getType() != Gem.META)
					valid_gem = true;
			}
			else if(gemSlotColor.equals("HYDRAULIC")){
				if(elem.getType() == Gem.HYDRAULIC)
					valid_gem = true;
			}
			double gemEP = calcGemEP(elem);
			if(valid_gem && (bestGem == null || gemEP > best)){
				bestGem = elem;
				best = gemEP;
			}
		}
		return bestGem;
	}
	
	public double calcGemEP(Item item, Gem gem,int gemSlot) {
		if(fast == null)
			return gem.getAgi()*2+gem.getHaste()+gem.getCrit()+gem.getExp()+gem.getHit()+gem.getMastery();
		Map<String,Double> statsEP = fast.getEP();
		double ep = statsEP.get("agi")*gem.getAgi();
		ep += statsEP.get("white_hit")*gem.getHit();
		ep += statsEP.get("exp")*gem.getExp();
		ep += statsEP.get("haste")*gem.getHaste();
		ep += statsEP.get("mastery")*gem.getMastery();
		ep += statsEP.get("crit")*gem.getCrit();
		
		// bring in some conditions like socketbonus
		if(		item.gemSlot[gemSlot].equals("RED") && (gem.getType() == Gem.RED || gem.getType() == Gem.PURPLE || gem.getType() == Gem.ORANGE) ||
				item.gemSlot[gemSlot].equals("YELLOW") && (gem.getType() == Gem.YELLOW || gem.getType() == Gem.ORANGE || gem.getType() == Gem.GREEN) ||
				item.gemSlot[gemSlot].equals("BLUE") && (gem.getType() == Gem.BLUE || gem.getType() == Gem.PURPLE || gem.getType() == Gem.GREEN)
			){
			double gemSocketEP = 0.;
			if(item.getSocketBonus() != null){
				SocketBonus sb = item.getSocketBonus();
				gemSocketEP += statsEP.get("agi")*sb.getAgi();
				gemSocketEP += statsEP.get("white_hit")*sb.getHit();
				gemSocketEP += statsEP.get("exp")*sb.getExp();
				gemSocketEP += statsEP.get("haste")*sb.getHaste();
				gemSocketEP += statsEP.get("mastery")*sb.getMastery();
				gemSocketEP += statsEP.get("crit")*sb.getCrit();
			}
			ep += gemSocketEP;
		}
		// gearbuffs...
		if(gem.getGearBuff() != null){
			try {
				ep += statsEP.get(gem.getGearBuff());
			}catch(Exception e){
				System.out.println("missing: " + gem.getName() + " " + gem.getGearBuff());
				View.showError("missing: " + gem.getName() + " " + gem.getGearBuff());
			}
		}
		
		return ep;
	}
	
	public double calcGemEP(Gem gem) {
		if(fast == null)
			return gem.getAgi()*2+gem.getHaste()+gem.getCrit()+gem.getExp()+gem.getHit()+gem.getMastery();
		Map<String,Double> statsEP = fast.getEP();
		double ep = statsEP.get("agi")*gem.getAgi();
		ep += statsEP.get("white_hit")*gem.getHit();
		ep += statsEP.get("exp")*gem.getExp();
		ep += statsEP.get("haste")*gem.getHaste();
		ep += statsEP.get("mastery")*gem.getMastery();
		ep += statsEP.get("crit")*gem.getCrit();
		// gearbuffs...
		if(gem.getGearBuff() != null){
			try {
				ep += statsEP.get(gem.getGearBuff());
			}catch(Exception e){
				System.out.println("missing: " + gem.getName() + " " + gem.getGearBuff());
				View.showError("missing: " + gem.getName() + " " + gem.getGearBuff());
			}
		}
		return ep;
	}
	
	public double calcEnchantEP(Enchant e,Slot slot) {
		if(fast == null || e == null)
			return 0.0;
		Map<String,Double> statsEP = fast.getEP();
		double ep = statsEP.get("agi")*e.getAgi();
		ep += statsEP.get("white_hit")*e.getHit();
		ep += statsEP.get("exp")*e.getExp();
		ep += statsEP.get("haste")*e.getHaste();
		ep += statsEP.get("mastery")*e.getMastery();
		ep += statsEP.get("crit")*e.getCrit();
		
		if(Slot.mainHand == slot && statsEP.get("mh_"+e.getName()) != null){
			ep += statsEP.get("mh_"+e.getName());
		}else if(Slot.offHand == slot && statsEP.get("oh_"+e.getName()) != null){
			ep += statsEP.get("oh_"+e.getName());
		}else if(Slot.back == slot && statsEP.get(e.getName()) != null){
			ep += statsEP.get(e.getName());
		}
		
		return ep;
	}
	
	public double calcReforgeEP(Item i,Reforge r){
		if(fast == null || i == null || r == null)
			return 0.0;
		Map<String,Double> statsEP = fast.getEP();
		int value = 0;
		double ep = 0;
		if(r.getFrom().equals("Haste Rating")){
			value = (int) Math.floor(i.getHaste() * 0.4);
			ep -= value * statsEP.get("haste");
		}else if(r.getFrom().equals("Hit Rating")){
			value = (int) Math.floor(i.getHit() * 0.4);
			ep -= value * statsEP.get("white_hit");
		}else if(r.getFrom().equals("Crit Rating")){
			value = (int) Math.floor(i.getCrit() * 0.4);
			ep -= value * statsEP.get("crit");
		}else if(r.getFrom().equals("Mastery Rating")){
			value = (int) Math.floor(i.getMastery() * 0.4);
			ep -= value * statsEP.get("mastery");
		}else if(r.getFrom().equals("Expertise Rating")){
			value = (int) Math.floor(i.getExp() * 0.4); 
			ep -= value * statsEP.get("exp");
		}
		
		if(r.getTo().equals("Haste Rating")){
			ep += value * statsEP.get("haste");
		}else if(r.getTo().equals("Hit Rating")){
			ep += value * statsEP.get("white_hit");
		}else if(r.getTo().equals("Crit Rating")){
			ep += value * statsEP.get("crit");
		}else if(r.getTo().equals("Mastery Rating")){
			ep += value * statsEP.get("mastery");
		}else if(r.getTo().equals("Expertise Rating")){
			ep += value * statsEP.get("exp");
		}
		
		return ep;
	}
	
	public void fillEquipment() {
		for(Slot slot : Slot.values()){
			System.out.println(slot);
			this.equipment.put(slot, new ItemEquipped());
		}
	}

	public void setEquipment(Equipment equipment) {
		this.equipment = equipment;
	}

	public Equipment getEquipment() {
		return equipment;
	}
	
	public IndzCraftLoader getLoader() {
		return loader;
	}

	public Database getDatabase() {
		return db;
	}
	
	public Stats getStats(){
		return fast.getStats();
	}

	public Map<String,Double> getEP() {
		if(fast == null)
			return new HashMap<String,Double>();
		return fast.getEP();
	}

	public void setSettings(Settings settings) {
		this.settings = settings;
	}

	public Settings getSettings() {
		return settings;
	}

	public void saveCharacter() {
		loader.save(equipment);
	}
}
